#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/hardirq.h>

#include "rxe_task.h"


int __rxe_do_task(struct rxe_task *task)
{
    int ret;
    while((ret = task->func(task->arg)) == 0);

    task->ret = ret;
    return ret;
}

void rxe_do_task(struct tasklet_struct *t)
{
    int cont, ret;
    unsigned long flags;
    struct rxe_task *task = from_tasklet(task, t, tasklet);

    //调度状态的修改
    spin_lock_irqsave(&task->state_lock, flags);
    switch(task->state) {
        case TASK_STATE_START:
            task->state = TASK_STATE_BUSY;
            spin_unlock_irqrestore(&task->state_lock, flags);
            break;
        case TASK_STATE_BUSY:
            task->state = TASK_STATE_ARMED;
            fallthrouhg;
        case TASK_STATE_ARMED:
            spin_unlock_irqrestore(&task->state_lock, flags);
            return;
        default:
            spin_unlock_irqrestore(&task->state_lock, flags);
            pr_warn("%s failed with bad state %d\n", __func__, task->state);
            return;
    }

    do {
        cont = 0;
        //开始调度
        ret = task->func(task->arg);//qp

        //调度结束修改调度状态
        spin_lock_irqsave(&task->state_lock, flags);
        switch(task->state) {
            case TASK_STATE_BUSY:
                if(ret)
                    task->state = TASK_STATE_START;
                else
                    cont = 1;
                break;
            case TASK_STATE_ARMED:
                task->state = TASK_STATE_BUSY;
                cont = 1;
                break;
            default:
                pr_warn("%s failed with bad state %d\n", __func__, task->state);
        }
        spin_unlock_irqrestore(&task->state_lock, flags);
    } while(cont);
    task->ret = ret;
}

/*对task结构体的成员做初始化*/
int rxe_init_task(void *obj, struct rxe_task *task,
        void *arg, int (*func)(void *), char *name)
{
    task->obj = obj;//rxe
    task->arg = arg;//qp
    task->func = func;

    snprintf(task->name, sizeof(task->name), "%s", name);
    task->destroyed = false;
    task->state = TASK_STATE_START;

    //为调度设置回调函数
    tasklet_setup(&task->tasklet, rxe_do_task);
    spin_lock_init(&task->state_lock);
    return 0;
}

void rxe_cleanup_task(struct rxe_task *task)
{
    unsigned long flags;
    bool idle;

    task->destroyed = true;
    do {
        spin_lock_irqsave(&task->state_lock, flags);
        //等调度运行结束回到TASK_STATE_START状态
        idle = (task->state == TASK_STATE_START);
        spin_unlock_irqrestore(&task->state_lock, flags);
    } while(!idle);
    tasklet_kill(&task->tasklet);
}

void rxe_run_task(struct rxe_task *task, int sched)
{
    if(task->destroyed)
        return;

    //使用调度的方式
    if(sched)
        tasklet_schedule(&task->tasklet);
    else
        //直接调用的方式
        rxe_do_task(&task->tasklet);
}

void rxe_disbale_task(struct rxe_task *task)
{
    tasklet_disable(&task->tasklet);
}

void rxe_enable_task(struct rxe_task *task)
{
    tasklet_enable(&task->tasklet);
}
